ECS(Fargate)上に構築したLocustからAPIサーバ(Go)経由で、TiDB Cloudにクエリを実行してみた
こんにちは、ゲームソリューション部のsoraです。
今回は、ECS(Fargate)上に構築したLocustからAPIサーバ(Go)経由で、TiDB Cloudにクエリを実行してみたことについて書いていきます。
TiDB Cloudクラスタの作成
まずTiDB Cloudにてクラスタを作成します。
今回はServerlessクラスタを作成します。
デフォルトで取得できるデータしか使用しないため、クラスタ作成して以下の接続コードを取得する以外の設定は不要です。
イメージの作成
dockerfileは以下折り畳みで記載します。
APIサーバ(Go)のdockerfile
FROM golang:alpine
WORKDIR /app
RUN apk update && apk add --no-cache git
COPY /src .
RUN go mod init app
RUN go mod tidy
CMD ["go", "run", "main.go"]
Locustのdockerfile
FROM locustio/locust
WORKDIR /locust
COPY locustfile.py /locust/locustfile.py
CMD ["-f", "/locust/locustfile.py"]
上記は以下記事にて作成したものを使用しております。
APIサーバ
APIサーバ(Go)のコードは以下です。
/locust-test
にリクエストがあった場合に、TiDB Cloudにクエリを実行するコードとなっています。
今回はテストのため、TiDB CloudのServerlessクラスタとはPublicで接続します。
package main
import (
"database/sql"
"log"
"net/http"
"crypto/tls"
"github.com/go-sql-driver/mysql"
)
// 起動するポート
const port = "8080"
func helloHandler(w http.ResponseWriter, r *http.Request) {
// データベース接続
// TiDB Cloudにて表示されたコード
mysql.RegisterTLSConfig("tidb", &tls.Config{
MinVersion: tls.VersionTLS12,
ServerName: "gateway01.ap-northeast-1.prod.aws.tidbcloud.com",
})
db, err := sql.Open("mysql", "xxxxxxxxxx.root:xxxxxxxxxx@tcp(gateway01.ap-northeast-1.prod.aws.tidbcloud.com:4000)/test?tls=tidb")
// エラー処理
if err != nil {
http.Error(w, "Failed to connect to database", http.StatusInternalServerError)
log.Printf("Failed to connect to database: %v", err)
return
}
// 関数終了時にコネクションを閉じる
defer db.Close()
// クエリ実行
rows, err := db.Query("SHOW DATABASES")
if err != nil {
http.Error(w, "Failed to execute query", http.StatusInternalServerError)
log.Printf("Failed to execute query: %v", err)
return
}
// 終了後にクエリ結果をリリース
defer rows.Close()
// クエリ結果をログ出力
for rows.Next() {
var dbName string
if err := rows.Scan(&dbName); err != nil {
log.Printf("Failed to scan row: %v", err)
return
}
log.Printf("%s", dbName)
}
if err = rows.Err(); err != nil {
log.Printf("Error occurred during rows iteration: %v", err)
return
}
}
func main() {
// ハンドラ関数を設定
http.HandleFunc("/locust-test", helloHandler)
// ログ出力
log.Printf("Server is running on port %s\n", port)
// サーバの起動
if err := http.ListenAndServe(":"+port, nil); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}
Locust
Locustのシナリオファイルは、/locust-test
にGETリクエストを実行するものとしています。
接続先ホストはGUI上で指定するため、シナリオファイルでは指定していません。
from locust import HttpUser, task, between
class QuickstartUser(HttpUser):
# ユーザーが次のタスクを実行するまでの待ち時間を1秒から2.5秒の間でランダムに設定
wait_time = between(1, 2.5)
# 負荷テスト中に行われるタスク
@task
def index_page(self):
self.client.get("/locust-test")
ECSタスク定義・サービスの立ち上げ
Locust・APIサーバ間はService Connectで接続します。
ログについて、APIサーバのタスク定義にてログドライバーをawslogsとして、アプリのログをCloudWatch Logsに出力するようにしています。
Service Connectのログも有効化しています。
接続確認
クラスタ内に2つのサービスがそれぞれ起動した後、http://{LocustのタスクのPublic IPアドレス}:8089
に接続して、HostとしてAPIサーバのService Connectのエンドポイントを指定すると、正常に実行できていることが確認できました。
CloudWatch Logsにてログを見てみると、クエリ実行により取得した結果が出力されていることが確認できました。
TiDB Cloudでもメトリクスを確認してみると、クエリが実行されていることが確認できました。
最後に
今回は、ECS(Fargate)上に構築したLocustからAPIサーバ(Go)経由で、TiDB Cloudにクエリを実行してみたことを記事にしました。
どなたかの参考になると幸いです。